package com.example.japinhands.ui.screen.newword

import android.os.Handler
import android.os.Message
import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Button
import androidx.compose.material3.Checkbox
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.example.japinhands.JapViewModel
import com.example.japinhands.data.DeformAdj
import com.example.japinhands.data.DeformVerb
import com.example.japinhands.data.Word
import com.example.japinhands.data.WordConstant
import com.example.japinhands.data.WordData
import com.example.japinhands.ui.screen.LeftRightItem
import com.example.japinhands.ui.screen.DeformAdjScreen
import com.example.japinhands.ui.screen.DeformVerbScreen
import com.example.japinhands.ui.screen.WordTypeUI
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.launch
import kotlin.concurrent.thread

@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class, FlowPreview::class)
@Composable
fun WordScreen(
    viewModel: JapViewModel,
    update: Boolean,
    word: Word? = null,
    adj: DeformAdj? = null,
    verb: DeformVerb? = null
) {
    val tag = "NewWordScreen"
    val mContext = LocalContext.current
//    val recomposeScope = currentRecomposeScope
    var wordData by remember {
        mutableStateOf(WordData())
    }
    var kanjiText by remember {
        mutableStateOf(wordData.kanjiText)
    }
    var ganaText by remember {
        mutableStateOf(wordData.ganaText)
    }
    var meaningText by remember {
        mutableStateOf(wordData.meaningText)
    }
    var noticeText by remember {
        mutableStateOf(wordData.noticeText)
    }
    var sentenceText by remember {
        mutableStateOf(wordData.sentenceText)
    }
    var showDeformVerb by remember {
        mutableStateOf(false)
    }
    var showDeformAdj by remember {
        mutableStateOf(false)
    }
    var checkedIndex by remember {
        mutableStateOf(wordData.wordType)
    }

    val showDeformJudge: (SnapshotStateList<WordTypeUI>, Int, Boolean) -> Unit = { list, i, check ->
        when (list[i].value) {
            WordConstant.VERB_1,
            WordConstant.VERB_2,
            WordConstant.VERB_3 -> {
                showDeformVerb = check
                showDeformAdj = false
            }

            WordConstant.ADJECTIVE_1,
            WordConstant.ADJECTIVE_2 -> {
                showDeformAdj = check
                showDeformVerb = false
            }

            else -> {
                showDeformVerb = false
                showDeformAdj = false
            }
        }
    }

    val wordTypeList = remember {
        mutableStateListOf<WordTypeUI>().apply {
            add(WordTypeUI(WordConstant.NOUN, "名词", false))
            add(WordTypeUI(WordConstant.VERB_1, "动1", false))
            add(WordTypeUI(WordConstant.VERB_2, "动2", false))
            add(WordTypeUI(WordConstant.VERB_3, "动3", false))
            add(WordTypeUI(WordConstant.ADJECTIVE_1, "形1", false))
            add(WordTypeUI(WordConstant.ADJECTIVE_2, "形2", false))
            add(WordTypeUI(WordConstant.ADVERB, "副词", false))
            add(WordTypeUI(WordConstant.CONJUNCTION, "连词", false))
            add(WordTypeUI(WordConstant.INTERJECTION, "感叹词", false))
            if (checkedIndex in 0..8) {
                this[checkedIndex] = this[checkedIndex].copy(isChecked = true)
                showDeformJudge(this, checkedIndex, true)
            }
        }
    }

    val onCheck: (index: Int, check: Boolean) -> Unit = { index, check ->
        if (index in 0..8) {
            wordTypeList[index] = wordTypeList[index].copy(isChecked = check)
        }
//        type.isChecked = check
//        wordTypeList[index].isChecked = check
        /*
         * 这里使用type.isChecked显示的是上一次的结果。所以猜测wordTypeList[index]
         * 中存的才是正确的值。经验证猜测正确。
         */
//        Log.d(tag, "Type ${type.name} isChecked: ${wordTypeList[index].isChecked}")
        /*
         * 使用for ((i, c) in wordTypeList.withIndex())时，抛出了
         * java.util.ConcurrentModificationException异常。改成下面的
         * 方式之后，异常消失。
         */
        for (i in wordTypeList.indices) {
            if (wordTypeList[i].isChecked && i != index) {
                wordTypeList[i] = wordTypeList[i].copy(isChecked = false)
//                wordTypeList[i].isChecked = false
            } else if (i == index) {
                // Save the type choice
                if (check) {
                    viewModel.saveWordTypeChoice(wordTypeList[i].value)
                    checkedIndex = i
                } else {
                    viewModel.saveWordTypeChoice(WordConstant.NONE)
                }
                showDeformJudge.invoke(wordTypeList, i, check)
            }
        }

    }


    val saveWord: () -> Unit = {
//        val sentenceKey = viewModel.sentenceLiveData.value?.key
//            ?: WordConstant.SENTENCE_KEY_NOT_EXIST
//        Log.d(tag, "sentence key: $sentenceKey")
        Log.d(tag, "Word type choice: ${viewModel.wordTypeChoice.value}")
        val wordToSave = Word(
            kanji = kanjiText,
            gana = ganaText,
            meaning = meaningText,
            notice = noticeText,
            type = checkedIndex,
            sentenceContent = sentenceText
        )
        Log.d(tag, "Save word: $wordToSave")
        viewModel.saveWord(wordToSave) {
            viewModel.allowSubmit = true
        }
    }

    val coroutineScope = rememberCoroutineScope()
    val inputFlow = remember {
        MutableSharedFlow<Unit>()
    }
    val queryFlow = remember {
        MutableSharedFlow<Int>()
    }
    val queryHandler by remember {
        mutableStateOf(object : Handler(mContext.mainLooper) {
            override fun handleMessage(msg: Message) {
                when (msg.what) {
                    200 -> Toast.makeText(mContext, "提交成功！", Toast.LENGTH_SHORT).show()
                    else -> Toast.makeText(mContext, "提交失败：$msg", Toast.LENGTH_SHORT).show()
                }
            }
        })
    }

    LaunchedEffect(word) {
        wordData = getUIData(update, word, viewModel)
        kanjiText = wordData.kanjiText
        ganaText = wordData.ganaText
        meaningText = wordData.meaningText
        noticeText = wordData.noticeText
        sentenceText = wordData.sentenceText
        checkedIndex = wordData.wordType
        onCheck.invoke(checkedIndex, true)
        viewModel.allowSubmit = false
        saveWord.invoke()
//        recomposeScope.invalidate()
        coroutineScope.launch {
            inputFlow
                .debounce(1000) // 停止输入多少号毫秒之后执行
//                .distinctUntilChanged()
                .collectLatest {
                    saveWord.invoke()
                }
        }
    }

    /**
     * Also works
     */
//    LaunchedEffect(Unit) {
//        coroutineScope.launch {
//            queryFlow.collectLatest {
//                if (it == 200) {
//                    Toast.makeText(mContext, "提交成功！", Toast.LENGTH_SHORT).show()
//                } else {
//                    Toast.makeText(mContext, "提交失败：$it", Toast.LENGTH_SHORT).show()
//                }
//            }
//        }
//    }

    

    LazyColumn {
        item {
            LeftRightItem(
                leftLabel = "日本語の漢字",
                rightLabel = "仮名",
                leftText = kanjiText,
                rightText = ganaText,
                onLeftChange = {
                    kanjiText = it
                    viewModel.allowSubmit = false
                    coroutineScope.launch { inputFlow.emit(Unit) } 
                },
                onRightChange = {
                    ganaText = it
                    viewModel.allowSubmit = false
                    coroutineScope.launch { inputFlow.emit(Unit) }
                }
            )
//            LeftRightItem(
//                leftLabel = "翻訳",
//                rightLabel = "重点",
//                leftText = meaningText,
//                rightText = noticeText,
//                onLeftChange = { meaningText = it; saveWord.invoke() },
//                onRightChange = { noticeText = it; saveWord.invoke() }
//            )
            TextField(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(8.dp),
                value = meaningText,
                onValueChange = {
                    meaningText = it
                    viewModel.allowSubmit = false
                    coroutineScope.launch { inputFlow.emit(Unit) }
                },
                label = { Text(text = "翻訳") }
            )
            TextField(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(8.dp),
                value = noticeText,
                onValueChange = {
                    noticeText = it
                    viewModel.allowSubmit = false
                    coroutineScope.launch { inputFlow.emit(Unit) }
//                    saveWord.invoke()
                },
                label = { Text(text = "重点") }
            )

            TextField(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(8.dp),
                value = sentenceText,
                onValueChange = {
                    sentenceText = it
                    viewModel.allowSubmit = false
                    coroutineScope.launch { inputFlow.emit(Unit) }
//                    saveWord.invoke()
                },
                label = { Text(text = "例句") }
            )

//            NewSentenceScreen(viewModel = viewModel)

            FlowRow {
                wordTypeList.forEachIndexed { index, type ->
                    Row {
                        Checkbox(
                            checked = wordTypeList[index].isChecked,
                            onCheckedChange = {
                                onCheck.invoke(index, it)
                                Log.d(tag, "index result: ${wordTypeList[index].isChecked}")
                                Log.d(tag, "type result: ${type.isChecked}")
                            }
                        )
                        Text(text = type.name, modifier = Modifier.clickable {
                            onCheck.invoke(index, !wordTypeList[index].isChecked)
                        })
                    }
                }
            }

            Button(onClick = {
                wordTypeList.forEach {
                    Log.d(tag, "${it.name} id: ${it.value}, checked: ${it.isChecked}")
                }
                Log.d(tag, "checkedIndex: $checkedIndex")
            }) {
                Text(text = "Check the checks")
            }

            if (showDeformVerb) {
                DeformVerbScreen(
                    viewModel = viewModel,
                    update = update,
                    verb = verb
                )
            }

            if (showDeformAdj) {
                DeformAdjScreen(
                    viewModel = viewModel,
                    update = update,
                    adj = adj
                )
            }

//            Button(onClick = {
//                Log.d(tag, "Verb: ${viewModel.deformVerbLiveData.value.toString()}")
//            }) {
//                Text(text = "Check Verb view model")
//            }

            Button(
                modifier = Modifier.fillMaxWidth(),
                onClick = {
    //                saveWord.invoke()
                    if (!viewModel.allowSubmit) {
                        Log.e(tag, "Do not allow submitting this time.")
                        Toast.makeText(mContext, "还在加载中哟~~~", Toast.LENGTH_SHORT).show()
                        return@Button
                    }
                    thread {
                        Log.d(tag, "Start submit word")
                        val id: Long?
                        if (update) {
                            var verbId = -1L
                            var adjId = -1L
                            when (viewModel.wordTypeChoice.value) {
                                WordConstant.VERB_1,
                                WordConstant.VERB_2,
                                WordConstant.VERB_3 -> {
                                    val wd = word
//                                    word?.deformVerb?.let {
//                                        viewModel.updateDeformVerb(it)
//                                        verbId = it
//                                    }
                                    if (word?.deformVerb != null && word.deformVerb != -1L) {
                                        verbId = word.deformVerb
                                        viewModel.updateDeformVerb(verbId)
                                    } else {
                                        verbId = viewModel.insertDeformVerb()
                                    }
                                }
                                WordConstant.ADJECTIVE_1,
                                WordConstant.ADJECTIVE_2 -> {
//                                    word?.deformAdj?.let {
//                                        viewModel.updateDeformAdj(it)
//                                        adjId = it
//                                    }
                                    if (word?.deformAdj != null && word.deformAdj != -1L) {
                                        adjId = word.deformAdj
                                        viewModel.updateDeformAdj(adjId)
                                    } else {
                                        adjId = viewModel.insertDeformAdj()
                                    }
                                }
                            }
                            id = word?.id
                            id?.let {
                                viewModel.updateWord(it, verbId, adjId)
                            }
                        } else {
                            when (viewModel.wordTypeChoice.value) {
                                WordConstant.VERB_1,
                                WordConstant.VERB_2,
                                WordConstant.VERB_3 -> {
                                    viewModel.insertDeformVerb()
                                }
                                WordConstant.ADJECTIVE_1,
                                WordConstant.ADJECTIVE_2 -> {
                                    viewModel.insertDeformAdj()
                                }
                            }
//                            viewModel.insertSentence()
                            id = viewModel.insertWord()
                        }

                        viewModel.queryWord(id ?: -1L) {
                            val msg = Message()
                            msg.what = if (it != null) {
//                                coroutineScope.launch {
//                                    queryFlow.emit(200)
//                                }
                                200
                            } else {
//                                coroutineScope.launch {
//                                    queryFlow.emit(400)
//                                }
                                400
                            }
                            queryHandler.sendMessage(msg)
                        }

                    }
                }
            ) {
                if (viewModel.allowSubmit) {
                    Text(text = if (update) "修改单词" else "添加单词")
                } else {
                    CircularProgressIndicator(
                        modifier = Modifier.size(20.dp),
                        color = Color(0x50660000),
                    )
                }
            }

//            Button(onClick = {
////                thread {
////                    viewModel.getAllWords().forEach {
////                        Log.d(tag, "Word: $it")
////                    }
////                }
//            }) {
//                Text(text = "Check word")
//            }

        } // end Item
    }
}

private fun getUIData(update: Boolean, word: Word?, viewModel: JapViewModel) = if (update) {
    var res = WordData()
    word?.let {
        res = WordData(it)
    }
    res
} else {
    WordData(
        kanjiText = viewModel.wordToInsert.value?.kanji ?: "",
        ganaText = viewModel.wordToInsert.value?.gana ?: "",
        meaningText = viewModel.wordToInsert.value?.meaning ?: "",
        noticeText = viewModel.wordToInsert.value?.notice ?: "",
        sentenceText = viewModel.wordToInsert.value?.sentenceContent ?: "",
        wordType = viewModel.wordTypeChoice.value ?: WordConstant.NONE
    )
}